#ifndef CRITERIA_H
#define CRITERIA_H

#include <list>
#include <cmath>
#include <memory>
#include <iostream>
#include <algorithm>
#include "people.h"

/// 过滤器
class Criteria
{
public:
    Criteria() {}
    virtual ~Criteria() {}
    virtual std::list<People> filter(std::list<People> filter_list) = 0;

protected:
    std::list<People> m_list;
};

/// 过滤器——挑选颜值高的人
class Criteria_Handsome :  public Criteria
{
public:
    Criteria_Handsome() {}
    ~Criteria_Handsome() {}
    std::list<People> filter(std::list<People> filter_list);
};

/// 过滤器——挑选身高大于lowHeight的人
class Criteria_Higher : public Criteria
{
public:
    Criteria_Higher(double low, double high):m_height_lower(low),m_height_higher(high) {}

    std::list<People> filter(std::list<People> filter_list);
private:
    double m_height_lower;   // 最低身高
    double m_height_higher;  // 最高身高
};

/// 过滤器——挑选适龄人群
class Criteria_Age : public Criteria
{
public:
    Criteria_Age(int low, int high):m_age_lower(low), m_age_higher(high){}
    std::list<People> filter(std::list<People> filter_list);
private:
    int m_age_lower;    // 最小年龄
    int m_age_higher;   // 最大年龄
};

/// 过滤器——挑选体重范围
class Criteria_Weight : public Criteria
{
public:
    Criteria_Weight(int low, int high):m_weight_lower(low), m_weight_higher(high){}
    std::list<People> filter(std::list<People> filter_list);
private:
    int m_weight_lower;    // 最小年龄
    int m_weight_higher;   // 最大年龄
};

/// 过滤器——选择性别
class Criteria_SEX : public Criteria
{
public:
    Criteria_SEX(People::SEX sex):m_sex(sex){}
    std::list<People> filter(std::list<People> filter_list);

private:
    People::SEX m_sex;
};


/// 组合器-满足一项即可
class Or_Criteria
{
public:
    std::list<People> filter(std::list<People> filter_list);
    void add_criteria(std::shared_ptr<Criteria> criteria);

private:
    std::list<People> m_list;
    std::list<std::shared_ptr<Criteria> > m_criteria_list;

};

/// 组合器-同时具备
class And_Criteria
{
public:
    std::list<People> filter(std::list<People> filter_list);
    void add_criteria(std::shared_ptr<Criteria> criteria);

private:
    std::list<People> m_list;
    std::list<std::shared_ptr<Criteria> > m_criteria_list;

};


#endif // CRITERIA_H
